package com.pj.three.ali_oss;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.pj.utils.sg.NbUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 阿里OSS工具类
 * @author kongyongshun
 *		
 *		<!-- 阿里OSS SDK -->
		<dependency>
			<groupId>com.aliyun.oss</groupId>
			<artifactId>aliyun-sdk-oss</artifactId>
			<version>2.8.3</version>
		</dependency>
 */
@Service
public class AliOssUtil {

	
	// 配置文件类 
	static AliOssConfig aliOssConfig;
	@Autowired
	public  void setAliOssConfig(AliOssConfig aliOssConfig) {
		AliOssUtil.aliOssConfig = aliOssConfig;
	}
	
	
	
	// 返回前台上传所需要的信息 
	// 自定义文件后缀名, 
	// way=方式 1=图片，2=视频，3=音频，11=pdf, 12=apk安装包 
	public static Map<String, Object> getSignInfo(String ext, int way){
		
		// -1
		if(ext == null) {
			ext = "png";
		}
		
		// 0 、 取参数 
		ext = ext.toLowerCase();	// 文件后缀转小写 
		String dir_name = null;	// 根路径后的文件区分路径 
		String file_handle = "";	// 文件处理参数
		String ext_list = null;	// 文件后缀集合 
		
		if(way == 1) {
			dir_name = aliOssConfig.dir_image;
			file_handle = aliOssConfig.file_handle_image;
			ext_list = aliOssConfig.ext_list_image;
			if(ext.equals("gif")){
				file_handle = "";	// gif不做处理		  //aliOssConfig.file_handle_gif;	// gif特殊处理 
			}
		} 
		if(way == 2) {
			dir_name = aliOssConfig.dir_video;
			ext_list = aliOssConfig.ext_list_video;
		}
		if(way == 3) {
			dir_name = aliOssConfig.dir_audio;
			ext_list = aliOssConfig.ext_list_audio;
		}
		if(way == 11) {
			dir_name = aliOssConfig.dir_pdf;
			ext_list = aliOssConfig.ext_list_pdf;
		}
		if(way == 12) {
			dir_name = aliOssConfig.dir_apk;
			ext_list = aliOssConfig.ext_list_apk;
		}
		
		
		// 1、验证参数是否合格 
		if(Arrays.asList(ext_list.split(",")).contains(ext) == false){
			throw new RuntimeException("无效的文件后缀名：" + ext);
		}

		// 2、计算目录与url 
		String file_dir = getFilePath(dir_name, ext);	// 上传目录
		String file_url = aliOssConfig.domain + "/" + file_dir;	// 文件最终url, 默认版
		String file_url_handle = file_url;	// 文件最终url，加处理参数的 
		String file_url_not_handle = file_url;	// 文件最终url，加处理参数的 
		if(NbUtil.isNull(file_handle) == false){
			file_url_handle += file_handle;	// 加上处理参数  
		}


		// 3、计算 policy 与 签名
		OSSClient ossClient = new OSSClient(aliOssConfig.endpoint, aliOssConfig.accessKeyID, aliOssConfig.accessKeySecret);
		String policyText = getPolicyText(ossClient, file_dir);
		String policyBase64 = base64encode(policyText);
		String signature = ossClient.calculatePostSignature(policyText);	// 签名 
		
		// 4、组织信息 
		Map<String, Object> map = new HashMap<>();
		
		// 必要信息
		map.put("OSSAccessKeyId", aliOssConfig.accessKeyID); 	// 账号Id
		map.put("key", file_dir); 								// 上传目录
		map.put("policy", policyBase64);						// 上传文件大小等信息 
		map.put("Signature", signature);						// 签名 
		map.put("x-oss-object-acl", aliOssConfig.x_oss_object_acl);  			// 文件读写权限 
		map.put("success_action_status", aliOssConfig.success_action_status);	// 通知阿里OSS上传成功后，状态返回 200, 默认 204 
		// map.put("file", "file"); 							// 上传文件，前台计算 
		
		// 次要信息 
		map.put("host", aliOssConfig.host); 					// 主机地址 
		map.put("file_url", file_url); 							// 文件最终url 默认的 
		map.put("file_url_handle", file_url_handle); 			// 文件最终url 加处理参数   
		map.put("file_url_not_handle", file_url_not_handle); 			// 文件最终url 不加处理参数  
		map.put("max_size", aliOssConfig.max_size); 				// 文件最大大小  
		map.put("ext_list", ext_list);				// 图片允许的后缀集合 
		
		return map;
	}
	
	
	
	
	
	
	// 返回Policy字符串 
	// oss对象，文件路径 
	private static String getPolicyText(OSSClient ossClient, String fileDir){

		Date expiration = new Date(System.currentTimeMillis() + aliOssConfig.sign_time);	// 计算签名到期时间 
		long max_size = aliOssConfig.max_size;		// 文件最大大小
		
		PolicyConditions policyConds = new PolicyConditions();
		policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, max_size);	// 设置文件最大大小
		policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, fileDir);			// 文件上传目录 
		return ossClient.generatePostPolicy(expiration, policyConds);			// 转字符串 
	}
	
	// 返回随机文件上传目录
	// 格式：根文件夹 + 文件专属文件夹 + 日期 + 随机文件名 + 后缀 
	private static String getFilePath(String dir_name, String ext){
		String root_dir = aliOssConfig.root_dir;
		String today = NbUtil.getNowString("yyyy/MM/dd/");
		// String wName = NbUtil.getRandomString(12);	// substring(8, 24);
		String fileName = NbUtil.getMarking28() + "." + ext;
		return root_dir + dir_name + today + fileName;
	}
	
	// 返回 Base64 编码后的字符串
	private static String base64encode(String str){
		try {
			return Base64Utils.encodeToString(str.getBytes("UTF-8"));
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e); 
		}
	}
	
	
}
